gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/ringdib/png.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							RingSDK多媒体类库 ringdib.lib
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//原文件名:png.cpp
//
//说明:载入PNG图象。
// 		PNG的解码/编码用到了两个现成的类库png.lib和zlib.lib,文件位置:
//			free_lib\png和free_lib\zlib.原始版权信息请见这两个类库目录中
//			的代码和版权信息。
//
**********************************************************************/
#define MAKE_SELF_LIB
#include "ringdib.h"
#include "png.h"

void ImportRGB(LPBYTE lpd,LPBYTE* lpb,int width,int height);
void ImportRGBA(LPBYTE lpd,LPBYTE* lpb,int width,int height);
void ImportGray(LPBYTE lpd,LPBYTE* lpb,int width,int height);
void ImportGrayA(LPBYTE lpd,LPBYTE* lpb,int width,int height);

BOOL LoadPNG(LPCTSTR szFilename,RingDIB* rdib,int iFlag,LPSTR lpszFormat)
{
	if(iFlag == DIB_GETFORMAT)
	{
		if(lpszFormat)
		{
			wsprintf(lpszFormat,"png");
			return TRUE;
		}
		else
			return FALSE;
	}
	
	ringFile rf(szFilename);
   rf.Open();

	int nread = 8;
	BYTE buffer[8];
	
	if(!rf.Read(buffer,nread,TRUE))
		return FALSE;	
	
	//检测文件头
	if(png_sig_cmp(buffer,0,nread) != 0)
		return FALSE;
	else if(iFlag == DIB_QUERYSUPPORT)
		return TRUE;

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
	if(png_ptr == NULL)
		return FALSE;

	png_infop info_ptr = png_create_info_struct(png_ptr);
	
	if(info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr,0,0);
		return FALSE;
	}
	
	//保存堆栈现场
	if(setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr,&info_ptr,0);
		return FALSE;
	}
	
	png_ptr->io_ptr = (png_voidp)rf.Handle();
	//恢复文件指针
	rf.Seek(0);
	//图象解码
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
	
	//导入解码后的图象数据
	if(rdib->Create(png_get_image_width(png_ptr,info_ptr),png_get_image_height(png_ptr,info_ptr)))
	{
		LPBYTE* lpb = png_get_rows(png_ptr,info_ptr);
		LPBYTE lpd = (LPBYTE)rdib->Data();

		//获取颜色信息
		switch(png_get_color_type(png_ptr,info_ptr))
		{
		case PNG_COLOR_TYPE_RGB:
			ImportRGB(lpd,lpb,rdib->Width(),rdib->Height());
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			ImportRGBA(lpd,lpb,rdib->Width(),rdib->Height());
			break;
		case PNG_COLOR_TYPE_GRAY:
			ImportGray(lpd,lpb,rdib->Width(),rdib->Height());
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			ImportGrayA(lpd,lpb,rdib->Width(),rdib->Height());
			break;
		}
	}
	//释放内存
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	
	rf.Close();
	return TRUE;
}

BOOL SavePNG(LPCTSTR szFilename,RingDIB* rdib)
{
	if(rdib)
	{
		return TRUE;
	}
	else
		return FALSE;
}

void ImportRGB(LPBYTE lpd,LPBYTE* lpb,int width,int height)
{
	int nwCnt = width * sizeof(COLORREF);
	int nw = width * 3;
	LPBYTE lpLine = lpd + (height - 1) * nwCnt;

	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < nw; j += 3)
		{
			*lpLine ++ = lpb[i][j + 2];	// blue
			*lpLine ++ = lpb[i][j + 1];	// green
			*lpLine ++ = lpb[i][j];		// red
			*lpLine ++;
		}
		
		lpLine -= (nwCnt << 1);
	}
}

void ImportRGBA(LPBYTE lpd,LPBYTE* lpb,int width,int height)
{
	int nwCnt = width * sizeof(COLORREF);
	LPBYTE lpLine = lpd + (height - 1) * nwCnt;

	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < nwCnt; j += 4)
		{
			*lpLine ++ = lpb[i][j + 2];	// blue
			*lpLine ++ = lpb[i][j + 1];	// green
			*lpLine ++ = lpb[i][j];		// red
			*lpLine ++ = lpb[i][j + 3];	// alpha
		}
		
		lpLine -= (nwCnt << 1);
	}
}

void ImportGray(LPBYTE lpd,LPBYTE* lpb,int width,int height)
{
	BYTE cr;
	COLORREF* lpLine = (COLORREF*)lpd;
	lpLine += (height - 1) * width;
	
	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < width; j ++)
		{
			cr = lpb[i][j];
			*lpLine ++ = RGB(cr,cr,cr);			
		}		
		lpLine -= (width << 1);
	}
}

void ImportGrayA(LPBYTE lpd,LPBYTE* lpb,int width,int height)
{
	BYTE cr;
	int nwCnt = width << 1;
	COLORREF* lpLine = (COLORREF*)lpd;
	lpLine += (height - 1) * width;
	
	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < nwCnt; j += 2)
		{
			cr = lpb[i][j];
			*lpLine ++ = (RGB(cr,cr,cr) | (((COLORREF)lpb[i][j+1]) << 24));			
		}		
		lpLine -= (width << 1);
	}
}